$FILE = "/Users/jdahern/Documents/Dropbox/CS372/ass8/database.txt"

###############################################################
# User
###############################################################
class User
  attr_reader :username, :name, :friends, :sex, :password
  attr_writer :username, :name, :sex, :password
  
  def initialize(username,name,friends,sex,password)
   @username = username
   @name = name
   @friends = friends
   @sex = sex
   @password = password
   # print to_out
  end

  def to_out
     s = ""
     @friends.each do |key, value|
           s = s + key + "/" + value + " "
         end
     n = "USERNAME\t#{@username}\nNAME\t\t#{@name}\nSEX\t\t#{@sex}\nPASSWORD\t#{@password}\nFRIENDS\t\t" + s + "\nEND\n\n"
     return n
  end
end
###############################################################
# Database
###############################################################
class Database
  @@db = {}
  def initialize()
    load()
  end
  
  def [] (username)
    users do |x|
      if(x[0] == username) then
        return x[1]
      end
    end
  end
  
  def []= (name,user)
    users do |x|
      if x[1].username == user then
        x[1].name = ""
        x[1].name = name
        save()
      end
    end
  end

  def users()
     @@db.find do |x|
       yield x
     end 
  end
  
  def exists_user?(name)
    out = ""
    users do |x|
      out = x[0]
      if (out) == name then
        return true
      end
    end
    return false
  end
  
  def add(username, userObj)
    @@db[username] = userObj
    save()
  end
    
  
	def exists_userpswd?(username, pswd)
	out = ""
		users do |x|
			out = x[0]
			if exists_user?(username) then
				if(x[1].password == pswd) then
					return true						
				end
			else
				return false		
			end	
		end
	end

  def read_line (database)
    File.open(database) do |file|
      file.each do |line| 
        if line =~ /[\t]/ then
          yield line
        elsif line =~ /[#]/ then
            # Do Nothing
        elsif line =~ /[a-z]+|\t+/ then
          yield line
        else
            # Do Nothing
          end
      end 
    end
  end
  
  def split_line (line)
    a = []
    line.scan(/[a-z]+[ ]*[a-z]+/) do |word|
      a << word
    end
    return a
  end
  
  def load()
    username = name = password = sex = nil
    friends = {}
    data = ""
    f = File.open($FILE, "r")
    f.each_line do |line|
      friends = {}
      args = line.scan(/[^\s]+/)
        case args[0]
          when "USERNAME" then username = args[1]
          when "NAME" then output = ""; for x in 1...args.length; output += "#{args[x]} "; end; name = output
          when "SEX" then sex = args[1]
          when "PASSWORD" then password = args[1]
          when "FRIENDS" then 
            j = 1
            while j < (args.length)
              for i in args[j].scan(/[a-zA-Z0-9\/]+/)
                a = i.scan(/[a-zA-Z0-9]+/)
                friends[a[0]] = a[1]
              end
              j += 1
            end
          @@db[username] = User.new(username,name,friends,sex,password)
        end
      end
      f.close
    end
  
  def save()
    outputstr = ""
    File.open($FILE, "w") do |file|
      users do |x|
        outputstr = ""
        outputstr = x[1].to_out
        file.puts "#{outputstr}"
      end
    end
  end
end


class Facebook
def Facebook.BFS(queue, visited, level)
  i = 0
  # Since queue starts with a name, just start popping the queue
	searched = queue.pop
  yield(searched, i)
  level << searched
	queue.push(searched)
	while queue.length > 0
		# pop off the node
		node = queue.pop
		# get the edges of the node
		addin = $database[node]
		# create the output string
		output = ""
		# scan thru the edges
		addin.each do |key, value|
			# if node has not been visited, then visit it
			if !visited[key] then
				visited[key] = true
				queue.push(key)
				output += key + " "
				level << key
			end
		end
		# make sure there is output to be printed
		if output != "" then
			i += 1
			yield(output, i)
		end
	end
end

def Facebook.levels3(username)
  visited = {username=>true}
  queue = [username]
  level = []
  BFS(queue, visited, level) do |x, y|
    temp = x.scan(/[a-zA-Z0-9]+/)
    yield(temp, temp.length)
  end
end

# This routine returns 'counts', an array where
# count[0] is the number of users at that level from the
# current user (always 0), count[1] is the user's number of
# direct friends, count[2] is the number of friends 2 steps
# away, etc.
def Facebook.levels(username)
  counts = []
  levels3(username) do |user,level|
    counts << level
  end
  return counts
end

a = Database.new()
levels("nopants")

end